package com.mexcad.db.connectors;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.mexcad.db.dto.Acreedor;
import com.mexcad.db.dto.CKAcreedor;
import com.mexcad.db.dto.CKCreditoAcreedor;
import com.mexcad.db.dto.CKGerente;
import com.mexcad.db.dto.CKPagoAcreedor;
import com.mexcad.db.dto.Cliente;
import com.mexcad.db.dto.Credito;
import com.mexcad.db.dto.CreditoAcreedor;
import com.mexcad.db.dto.Gerente;
import com.mexcad.db.dto.PagoAcreedor;
import com.mexcad.db.dto.Solicitud;
import com.mexcad.db.utils.ExceptionDB;
import com.mexcad.db.utils.HibernateUtil;
import com.mexcad.utils.Formatter;

public class AcreedorConnector {

	public static final int CREDITO_ACTIVO = 1;
	public static final int CREDITO_CONCLUIDO = 2;
	public static final int CREDITO_CANCELADO = 3;
	public static final int CREDITO_PAGO_ANTICIPADO = 4;
	
	public static final int PAGO_COMPLETADO = 5;
	
	public static final int ESQUEMA_NORMAL = 1;
	public static final int ESQUEMA_IVA = 2;
	
	
//	public static final int CREDITO_PAGO_ANTICIPADO = 4;
//	public static final int CREDITO_PAGO_ANTICIPADO = 4;
	
	
	
	
	private static Log logger = LogFactory.getLog(ClienteConnector.class);
	public AcreedorConnector(){
		logger.debug("Instanciating AcreedorConnector");
	}
	
	public static Acreedor getInstanciaAcreedor(){
		return new Acreedor();
	}
	public static CKAcreedor getInstanciaCKAcreedor(){
		return new CKAcreedor();
	}

	public static CreditoAcreedor getInstanciaCreditoAcreedor(){
		return new CreditoAcreedor();
	}
	public static CKCreditoAcreedor getInstanciaCKCreditoAcreedor(){
		return new CKCreditoAcreedor();
	}
	
	public static List<Acreedor> getAllAcreedores() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM Acreedor";
		List<Acreedor> lista=session.createQuery(query).list();
		//System.out.println(lista);
		session.close();
		return lista;	
	}
	
	
	
	public static Acreedor getAcreedorById(int idAcc){
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM Acreedor where ckAcreedor.idAcreedor="+idAcc;
		Acreedor acc=(Acreedor)session.createQuery(query).uniqueResult();
		//System.out.println(lista);
		session.close();
		return acc;	
		
	}
		
	

	public static synchronized int guardaAcreedor(Acreedor ac){
		try{
			ac.setApellidoPaterno(ac.getApellidoPaterno().toUpperCase());
			ac.setApellidoMaterno(ac.getApellidoMaterno().toUpperCase());
			ac.setNombres(ac.getNombres().toUpperCase());
			if(ac.getDescripcion() == null)
				ac.setDescripcion("");
			
			if(ac.getRfc() == null)
				ac.setRfc("");
			else
				ac.setRfc(ac.getRfc().toUpperCase());
			
			Session session = HibernateUtil.getSessionFactory().openSession();
			Transaction transaction = session.beginTransaction();
			
			ac.setFechaRegistro(Formatter.getFechaHoraActual());
			logger.debug("Querying AcreedorConnector");
			if(ac.getCkAcreedor().getIdAcreedor() == 0){
				ac.getCkAcreedor().setIdAcreedor(getUltimoIdAcreedor());
			}
			session.saveOrUpdate(ac);
			transaction.commit();

			session.close();
			
			return ac.getCkAcreedor().getIdAcreedor();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			return ExceptionDB.getNumMessageDB(excepts);
		}catch(Exception e){
			return ExceptionDB.getNumMessageDB(e);
		} 
		
	}
	

	public static synchronized int guardaCreditoAcreedor(CreditoAcreedor cred){
		try{
			
			Session session = HibernateUtil.getSessionFactory().openSession();
			Transaction transaction = session.beginTransaction();
			cred.setFechaCreacion( Formatter.getFechaHoraActual());
			if(cred.getDescripcion()==null){
				cred.setDescripcion("");
			}
			
			logger.debug("Querying AcreedorConnector");
			if(cred.getCkCreditoAcreedor().getIdCreditoAcreedor() == 0){
				cred.setIdEstatusCreditoAcc(AcreedorConnector.CREDITO_ACTIVO);
				cred.setMontoCreditoTotal(cred.getCapital());
				cred.setMontoRestante(cred.getCapital());
				
				cred.getCkCreditoAcreedor().setIdCreditoAcreedor(getUltimoIdCreditoAcreedor());
			}
			
			session.saveOrUpdate(cred);
			transaction.commit();

			session.close();
			
			return cred.getCkCreditoAcreedor().getIdCreditoAcreedor();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			return ExceptionDB.getNumMessageDB(excepts);
		}catch(Exception e){
			return ExceptionDB.getNumMessageDB(e);
		} 
		
	}
	
	public static CreditoAcreedor actualizaInteresesDeCreditoAcreedor(CreditoAcreedor credito, String fecha){
		if(credito !=null && fecha !=null){
			
			Date getFechaCalculoInt = credito.getFechaCalculoIntereses();
			if(getFechaCalculoInt == null){
				getFechaCalculoInt = credito.getFechaInicial();
			}
			
			int dias =Formatter.getDiasByPeriodo(Formatter.getStringFromDate(getFechaCalculoInt),fecha);
			if(dias < 0){
				return null;
			}
			credito.setFechaCalculoIntereses(Formatter.getDateFromString(fecha));
			
			double capital = credito.getCapital();
			double tasaDia=credito.getTasaBase()/365;
			double intereses=capital*dias*tasaDia/100;
			
			credito.setIntereses(intereses+credito.getIntereses());
			credito.setInteresesAcumulados(credito.getInteresesAcumulados()+intereses);
			
			if(credito.getCkCreditoAcreedor().getIdEsquemaCreditoAc() == AcreedorConnector.ESQUEMA_NORMAL){
				credito.setMontoCreditoTotal(credito.getCapital()+credito.getInteresesAcumulados());
				credito.setMontoRestante(credito.getCapital()+credito.getIntereses());
				
			}else if(credito.getCkCreditoAcreedor().getIdEsquemaCreditoAc() == AcreedorConnector.ESQUEMA_IVA){
				credito.setImpuestos(credito.getImpuestos()+intereses*CreditoConnector.IVA);
				credito.setMontoCreditoTotal(credito.getCapital()+credito.getInteresesAcumulados()+credito.getImpuestos());
				credito.setMontoRestante(credito.getCapital()+credito.getIntereses()+credito.getImpuestos());
			}
		}
		
		AcreedorConnector.guardaCreditoAcreedor(credito);
		return credito;
	}
	
	public static int actualizaInteresesDeCreditoAcreedor(int idCredito, String fecha){
		CreditoAcreedor credito = AcreedorConnector.getCreditoAcreedorById(idCredito);
		if(credito !=null && fecha !=null){
			
			Date getFechaCalculoInt = credito.getFechaCalculoIntereses();
			if(getFechaCalculoInt == null){
				getFechaCalculoInt = credito.getFechaInicial();
			}
			
			int dias =Formatter.getDiasByPeriodo(Formatter.getStringFromDate(getFechaCalculoInt),fecha);
			if(dias < 0){
				return -1;
			}
			credito.setFechaCalculoIntereses(Formatter.getDateFromString(fecha));
			
			double capital = credito.getCapital();
			double tasaDia=credito.getTasaBase()/365;
			double intereses=capital*dias*tasaDia/100;
			
			credito.setIntereses(intereses+credito.getIntereses());
			credito.setInteresesAcumulados(credito.getInteresesAcumulados()+intereses);
			
			if(credito.getCkCreditoAcreedor().getIdEsquemaCreditoAc() == AcreedorConnector.ESQUEMA_NORMAL){
				credito.setMontoCreditoTotal(credito.getCapital()+credito.getInteresesAcumulados());
				credito.setMontoRestante(credito.getCapital()+credito.getIntereses());
				
			}else if(credito.getCkCreditoAcreedor().getIdEsquemaCreditoAc() == AcreedorConnector.ESQUEMA_IVA){
				credito.setImpuestos(credito.getImpuestos()+intereses*CreditoConnector.IVA);
				credito.setMontoCreditoTotal(credito.getCapital()+credito.getInteresesAcumulados()+credito.getImpuestos());
				credito.setMontoRestante(credito.getCapital()+credito.getIntereses()+credito.getImpuestos());
			}
		}
		
		AcreedorConnector.guardaCreditoAcreedor(credito);
		
		return credito.getCkCreditoAcreedor().getIdCreditoAcreedor();
	}
	

	
	
	public static synchronized int guardaPagoAcreedor(int idCred, double monto, String fecha){
		try{
			
			Session session = HibernateUtil.getSessionFactory().openSession();
			Transaction transaction = session.beginTransaction();
			
			CreditoAcreedor credito = AcreedorConnector.getCreditoAcreedorById(idCred);
			PagoAcreedor pago = new PagoAcreedor();
			CKPagoAcreedor ck = new CKPagoAcreedor();
			
			credito =actualizaInteresesDeCreditoAcreedor(credito, fecha);
			if(credito == null){
				return -1;
			}
			double capital = credito.getCapital();
			double iva = credito.getImpuestos();
			double intereses = credito.getIntereses();
			
			
			if(credito.getCkCreditoAcreedor().getIdEsquemaCreditoAc()== AcreedorConnector.ESQUEMA_NORMAL){

				double montorestante = monto - intereses;
				pago.setAbono(monto);
				ck.setIdCreditoAcreedor(credito.getCkCreditoAcreedor().getIdCreditoAcreedor());
				pago.setCkPagoAcreedor(ck);
							
				if(montorestante <= 0){ // se pagaron parcialmente los intereses y monto despues es cero
					pago.setIntereses( monto);					
					credito.setIntereses(credito.getIntereses()- monto);
					
					credito.setMontoRestante(credito.getMontoRestante()-monto);	 
					pago.setSaldo(credito.getMontoRestante());

					
				}else if(montorestante > 0){
					//double resto = montorestante-credito.getIntereses();
					pago.setIntereses(credito.getIntereses());
					credito.setIntereses(0.0);
					credito.setMontoRestante(credito.getMontoRestante()-intereses);	 
					
					pago.setCapital(montorestante);
					credito.setCapital(credito.getCapital()-montorestante);
					credito.setMontoRestante(credito.getMontoRestante()-montorestante);
					
					pago.setSaldo(credito.getMontoRestante());
					
					
				}
				
								
				
			}else if(credito.getCkCreditoAcreedor().getIdEsquemaCreditoAc()== AcreedorConnector.ESQUEMA_IVA){
			
				
				double montorestante = monto - intereses;
				pago.setAbono(monto);
				ck.setIdCreditoAcreedor(credito.getCkCreditoAcreedor().getIdCreditoAcreedor());
				pago.setCkPagoAcreedor(ck);
				
				if(monto < credito.getIntereses()){
					pago.setIntereses(monto);
					credito.setIntereses(credito.getIntereses()-monto);
					credito.setMontoRestante(credito.getMontoRestante()-monto);
					
				}else{
					pago.setIntereses(credito.getIntereses());
					credito.setMontoRestante(credito.getMontoRestante()-credito.getIntereses());
					monto =monto-credito.getIntereses();
					credito.setIntereses(0);
					if(monto < credito.getImpuestos()){
						pago.setImpuestos(monto);
						credito.setImpuestos(credito.getImpuestos()-monto);
						credito.setMontoRestante(credito.getMontoRestante()-monto);
						
					}else{
						pago.setImpuestos(credito.getImpuestos());
						credito.setMontoRestante(credito.getMontoRestante()-credito.getImpuestos());
						monto=monto-credito.getImpuestos();
						credito.setImpuestos(0);
						if(monto > 0){ 
							pago.setCapital(monto);
							credito.setMontoRestante(credito.getMontoRestante()-monto);
							credito.setCapital(credito.getCapital()-monto);
							
						}
						
					}
					
				}
			}

			pago.setSaldo(credito.getMontoRestante());
				
			if(CreditoConnector.getDoubleCentesimas(credito.getMontoRestante()) == 0){
				credito.setIdEstatusCreditoAcc(AcreedorConnector.CREDITO_CONCLUIDO);
				credito.setMontoRestante(CreditoConnector.getDoubleCentesimas(credito.getMontoRestante()));
				credito.setCapital(CreditoConnector.getDoubleCentesimas(credito.getCapital()));
				 	
			}
			pago.setIdEstatusCreditoAcc(AcreedorConnector.PAGO_COMPLETADO);
			pago.setNumPago(getNumCargoPago(credito.getCkCreditoAcreedor().getIdCreditoAcreedor()));
			pago.setFechaRegistro(Formatter.getDateFromString(fecha));
			if(pago.getDescripcion()==null){
				pago.setDescripcion("");
			}
			
			logger.debug("Querying AcreedorConnector");
			if(pago.getCkPagoAcreedor().getIdPagoAcreedor() == 0){
	
				pago.getCkPagoAcreedor().setIdPagoAcreedor(getUltimoIdPagoAcreedor());
			}
			
			session.saveOrUpdate(pago);
			session.saveOrUpdate(credito);
			
			transaction.commit();

			session.close();
			
			return pago.getCkPagoAcreedor().getIdPagoAcreedor();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			return ExceptionDB.getNumMessageDB(excepts);
		}catch(Exception e){
			return ExceptionDB.getNumMessageDB(e);
		} 
		
	}
	
	private static int getNumCargoPago(int idCredito) {

		
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query = "select count(*) from PagoAcreedor where ckPagoAcreedor.idCreditoAcreedor= "+idCredito;
	
		Integer max = (Integer) session.createQuery(query).uniqueResult();
		session.close();
		
		if(max==null)
			return 1;
		else
			return max+1;
		
	}
	
	private static   int getUltimoIdAcreedor(){
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query = "select max(ckAcreedor.idAcreedor) from Acreedor ";
		Integer folio =null;
		try{
			folio = (Integer) session.createQuery(query).uniqueResult();
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		
		if(folio==null)
			return 1;
		else
			return folio+1;
		
	}
	
	private static   int getUltimoIdCreditoAcreedor(){
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query = "select max(ckCreditoAcreedor.idCreditoAcreedor) from CreditoAcreedor ";
		Integer folio = null;
		try {
			folio = (Integer) session.createQuery(query).uniqueResult();
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		if(folio==null)
			return 1;
		else
			return folio+1;
	}
	
	private static   int getUltimoIdPagoAcreedor(){
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query = "select max(ckPagoAcreedor.idPagoAcreedor) from PagoAcreedor ";
		Integer folio =null;
		try{
			folio = (Integer) session.createQuery(query).uniqueResult();
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		if(folio==null)
			return 1;
		else
			return folio+1;
	}
	
	
	
	
	
	public static synchronized void eliminaAcreedor(int idAcreedor) {
		
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = session.beginTransaction();
		
		Acreedor acc= getAcreedorById(idAcreedor);
		
		try{
			session.delete(acc);
			transaction.commit();
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			transaction.rollback();
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			transaction.rollback();
			if(session!= null && session.isOpen())
				session.close();
			
		}
		
	}
	
	public static List<CreditoAcreedor> getAllCreditosAcreedoresByStatus(int status) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM CreditoAcreedor where idEstatusCreditoAcc="+status;
		List<CreditoAcreedor> lista=null;
		try{
			lista=session.createQuery(query).list();
			//System.out.println(lista);
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		return lista;	
	}
	public static List<CreditoAcreedor> getAllCreditosAcreedoresByIdAcreedor(int idAcc) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM CreditoAcreedor where ckCreditoAcreedor.idAcreedor="+idAcc;
			List<CreditoAcreedor> lista=null;
		try{	
			lista=session.createQuery(query).list();
			//System.out.println(lista);
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		return lista;	
	}
	
	
	public static List<CreditoAcreedor> getAllCreditosAcreedores() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM CreditoAcreedor";
		List<CreditoAcreedor> lista=null;
		try{
			lista=session.createQuery(query).list();
			//System.out.println(lista);
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		return lista;	
	}
	
	public static CreditoAcreedor getCreditoAcreedorById(int idCred){
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM CreditoAcreedor where ckCreditoAcreedor.idCreditoAcreedor="+idCred;
		CreditoAcreedor acc=null;
		try{
			acc=(CreditoAcreedor)session.createQuery(query).uniqueResult();
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		return acc;	
		
	}
	
	
	public static List<CreditoAcreedor> getListadoCreditoAcreedorById(int idAcc){
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM CreditoAcreedor where ckCreditoAcreedor.idAcreedor="+idAcc;
		List<CreditoAcreedor> acc=session.createQuery(query).list();
		//System.out.println(lista);
		session.close();
		return acc;	
		
	}

	public static List<PagoAcreedor> getAllPagosCreditoAccByIdCredito(int idCredito){
		Session session = HibernateUtil.getSessionFactory().openSession();
		String query ="FROM PagoAcreedor where ckPagoAcreedor.idCreditoAcreedor="+idCredito;
		List<PagoAcreedor> acc=null;
		try{
			acc=session.createQuery(query).list();
		//System.out.println(lista);
			session.close();
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		return acc;	
		
	}
	

	public static void main(String []a){
		AcreedorConnector.buscarCreditosAcreedores("2", "2", "21/03/2009", "03/12/2010");
	}
	
	public static int getDiasDesdeInicio(String fecha1, String fecha2){
		return Formatter.getDiasByPeriodo(fecha1,  fecha2);
	}
	
	public static List<CreditoAcreedor> buscarCreditosAcreedores(String idAcreedor, String idEstatus,  String fechaInicial, String fechaFinal){
	//public static List<Solicitud> buscarSolicitudes(String ...listadoStrings){
		String []identificadores= {" cred.ckCreditoAcreedor.idAcreedor=",
								   " cred.idEstatusCreditoAcc=",
								   " cred.fechaCreacion>= '",
								   " cred.fechaCreacion < '"};	
		
		String []listadoStrings={idAcreedor, idEstatus,  fechaInicial,  fechaFinal};
		Session session = HibernateUtil.getSessionFactory().openSession();
		List<CreditoAcreedor> lista= null;
		try{
			logger.debug("Querying Solicitud");
			int cont=0;

			String query =" FROM  CreditoAcreedor cred \n";
	
			lista = new ArrayList<CreditoAcreedor>();
	
				
			for(int i=0;i<listadoStrings.length;++i){
					if(listadoStrings[i].length()>0)
					  cont++;	
			}
			if(cont > 0){
					query+=" where \n";
					
					for(int i=0;i<listadoStrings.length;++i){
						if(listadoStrings[i].length() > 0){
							query+=identificadores[i]+listadoStrings[i];
							
							if(i>=2 ){
								query+="' ";
							}
							if(cont>1){
								query+=" AND \n";
							}	
							cont--;
						}
						
						  
					}
			}
			lista= session.createQuery(query).list();
			session.close();
				
		}catch(org.hibernate.exception.GenericJDBCException excepts){
			if(session!= null&& session.isOpen())
				session.close();
			
		}catch(Exception e){
			if(session!= null&& session.isOpen())
				session.close();
			
		} finally{
			if(session!= null && session.isOpen())
				session.close();
			
		}
		
		
	
		return lista;
	}
	

	
	
	
}
